package com.ac.scum.log.web.model.player.controller;

import com.ac.common.core.exception.BaseException;
import com.ac.common.core.exception.config.ExceptionType;
import com.ac.common.core.result.Result;
import com.ac.scum.log.bean.Package;
import com.ac.scum.log.bean.*;
import com.ac.scum.log.web.model.card.mapper.CardMapper;
import com.ac.scum.log.web.model.card.mapper.CardUsedMapper;
import com.ac.scum.log.web.model.pack.mapper.PackageMapper;
import com.ac.scum.log.web.model.player.controller.vo.BindPlayerAlarmPushedVO;
import com.ac.scum.log.web.model.player.dto.PlayerAlarmPushedDTO;
import com.ac.scum.log.web.model.player.mapper.PlayerAlarmPushedMapper;
import com.ac.scum.log.web.model.player.mapper.PlayerMapper;
import com.ac.scum.log.web.model.server.mapper.ServerMapper;
import com.ac.scum.log.web.model.wechat.mp.mapper.WeChatUserMapper;
import com.ac.scum.log.web.model.wechat.mp.mapper.WeChatUserPlayerMapper;
import com.ac.scum.log.web.model.wechat.mp.service.TemplateSendService;
import com.ac.scum.log.web.utils.spring.SpringUtils;
import com.ac.scum.log.web.utils.user.CurrentUserUtil;
import com.ac.scum.wechat.bean.WeChatUser;
import com.ac.scum.wechat.bean.WechatUserPlayer;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.bean.template.WxMpTemplateData;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author : acfan
 * date : create in 2024/5/28 18:56
 * description : 玩家已推送报警
 **/
@Slf4j
@RestController
@AllArgsConstructor
@RequestMapping("player/alarm/pushed")
public class AlarmPushedController {

    private final PlayerAlarmPushedMapper playerAlarmPushedMapper;
    private final WeChatUserPlayerMapper weChatUserPlayerMapper;
    private final PlayerMapper playerMapper;
    private final WeChatUserMapper weChatUserMapper;
    private final ServerMapper serverMapper;
    private final CardMapper cardMapper;

    private final PackageMapper packageMapper;
    private final CardUsedMapper cardUsedMapper;

    @GetMapping("page/{current}/{size}")
    public Result<Page<PlayerAlarmPushedDTO>> page(@PathVariable("current") Long current, @PathVariable("size") Long size) throws BaseException {
        Page<PlayerAlarmPushed> playerAlarmPushedPage = playerAlarmPushedMapper.selectPage(new Page<>(current, size), Wrappers.lambdaQuery(PlayerAlarmPushed.class).eq(PlayerAlarm::getServerId, CurrentUserUtil.getCurrentServerId()));
        Page<PlayerAlarmPushedDTO> playerAlarmPushedDTOPage = new Page<>();
        List<PlayerAlarmPushedDTO> playerAlarmPushedDTOList = Lists.newArrayList();
        List<PlayerAlarmPushed> records = playerAlarmPushedPage.getRecords();
        Map<Long, Player> playerMap = Maps.newHashMap();
        try {
            playerMap = playerMapper.findPlayerByServerIdAndIds(CurrentUserUtil.getCurrentServerId(), records.stream().map(PlayerAlarm::getPlayerId).collect(Collectors.toList())).stream().collect(Collectors.toMap(Player::getId, Function.identity(), (old, news) -> news));
        } catch (Exception e) {
            log.error("获取玩家信息失败", e);
        }

        for (PlayerAlarmPushed record : records) {
            PlayerAlarmPushedDTO playerAlarmPushedDTO = new PlayerAlarmPushedDTO();
            playerAlarmPushedDTO.setPlayerAlarm(record);
            playerAlarmPushedDTO.setPushTime(record.getPushTime());
            playerAlarmPushedDTO.setPlayer(playerMap.get(record.getPlayerId()));
            playerAlarmPushedDTOList.add(playerAlarmPushedDTO);
        }
        playerAlarmPushedDTOPage.setRecords(playerAlarmPushedDTOList);
        playerAlarmPushedDTOPage.setTotal(playerAlarmPushedPage.getTotal());
        return Result.ok(playerAlarmPushedDTOPage);
    }

    @PostMapping("bind")
    public Result<Boolean> bind(@RequestBody BindPlayerAlarmPushedVO bindPlayerAlarmPushedVO) throws BaseException {
        if (serverMapper.selectById(bindPlayerAlarmPushedVO.getServerId()) == null) {
            throw new BaseException(ExceptionType.Parameter_Error.of("服务器不正确"));
        }
        List<WechatUserPlayer> wechatUserPlayers = weChatUserPlayerMapper.selectList(Wrappers.lambdaQuery(WechatUserPlayer.class)
                .eq(WechatUserPlayer::getSteamId, bindPlayerAlarmPushedVO.getSteamId())
                .or()
                .eq(WechatUserPlayer::getOpenId, bindPlayerAlarmPushedVO.getOpenId()));
        if (!wechatUserPlayers.isEmpty()) {
            throw new BaseException(ExceptionType.Parameter_Error.of("已绑定过其他账号"));
        }
        Player player = playerMapper.selectOne(Wrappers.lambdaQuery(Player.class).eq(Player::getSteamId, bindPlayerAlarmPushedVO.getSteamId()));
        if (player == null) {
            throw new BaseException(ExceptionType.Parameter_Error.of("未在本系统中匹配到与该SteamID一致的玩家，请加入使用本系统的游戏服务器中游玩。"));
        }
        WeChatUser weChatUser = weChatUserMapper.selectByOpenId(bindPlayerAlarmPushedVO.getOpenId());
        if (weChatUser == null || StringUtils.isBlank(weChatUser.getNickname())) {
            throw new BaseException(ExceptionType.Parameter_Error.of("请先“授权”，成功后在进行绑定操作"));
        }
        WechatUserPlayer wechatUserPlayer = new WechatUserPlayer();
        wechatUserPlayer.setPlayerId(player.getId());
        wechatUserPlayer.setSteamId(player.getSteamId());
        wechatUserPlayer.setBindTime(LocalDateTime.now());
        wechatUserPlayer.setOpenId(bindPlayerAlarmPushedVO.getOpenId());
        weChatUserPlayerMapper.insert(wechatUserPlayer);
        boolean result = activeTipPackage(bindPlayerAlarmPushedVO.getOpenId(), bindPlayerAlarmPushedVO.getServerId(), bindPlayerAlarmPushedVO.getKeyCard());
        try {
            SpringUtils.getBean(TemplateSendService.class).sendTemplate(bindPlayerAlarmPushedVO.getOpenId(), "3l4POJ32QOYAcMaW9fHtDuiFs1P_AyTb9urIUk2sMgU", new ArrayList<>() {{
                add(new WxMpTemplateData("character_string2", player.getSteamId().toString()));
                add(new WxMpTemplateData("thing3", weChatUser.getNickname()));
            }});
        } catch (WxErrorException e) {
            throw new BaseException(ExceptionType.System_Error.of("绑定成功通知发送失败:" + e.getMessage()));
        }
        return Result.ok(result);
    }

    public boolean activeTipPackage(String openId, Long serverId, String keyCard) throws BaseException {
        Player player = weChatUserPlayerMapper.selectPlayerByOpenId(openId);
        if (player == null) {
            throw new BaseException(ExceptionType.Parameter_Error.of("请先绑定"));
        }
        Card card = cardMapper.selectOne(Wrappers.lambdaQuery(Card.class).eq(Card::getKeyCard, keyCard));
        if (card == null || card.getUsed() || !card.getPackageId().equals(1796048740967038977L)) {
            throw new BaseException(ExceptionType.Card_Not_Found);
        }
        if (card.getType().equals(2) && cardUsedMapper.selectCount(Wrappers.lambdaQuery(CardUsed.class).eq(CardUsed::getCardId, card.getId()).eq(CardUsed::getSteamId, player.getSteamId())) > 0) {
            throw new BaseException(ExceptionType.System_Error.of("该卡密不允许重复使用"));
        }
        com.ac.scum.log.bean.Package pack = packageMapper.selectBySteamIdAndPackageId(player.getSteamId(), card.getPackageId());
        if (pack != null && pack.getId().equals(card.getPackageId())) {
            pack.setExpirationTime((pack.getExpirationTime().isBefore(LocalDateTime.now()) ? LocalDateTime.now() : pack.getExpirationTime()).plusHours(card.getHours()));
            packageMapper.updatePackageAsPlayer(pack);
        } else {
            pack = new Package();
            pack.setPlayerId(player.getId());
            pack.setServerId(serverId);
            pack.setSteamId(player.getSteamId());
            pack.setExpirationTime(LocalDateTime.now().plusHours(card.getHours()));
            pack.setId(card.getPackageId());
            packageMapper.insertPackageAsPlayer(pack);
        }
        if (card.getType() == 1) {
            card.setUsed(true);
            card.setUseTime(LocalDateTime.now());
            card.setUseId(player.getSteamId());
            cardMapper.updateById(card);
        }
        if (card.getType() == 2) {
            cardUsedMapper.insert(new CardUsed() {{
                setCardId(card.getId());
                setServerId(serverId);
                setSteamId(player.getSteamId());
            }});
        }
        return Boolean.TRUE;
    }
}
